﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

/*
 * PicWidthInMbs=pic_width_in_mbs_minus1 + 1
 * PicHeightInMbs = FrameHeightInMbs / ( 1 + field_pic_flag )
 * FrameHeightInMbs = ( 2 – frame_mbs_only_flag ) * PicHeightInMapUnits
 * PicHeightInMapUnits = pic_height_in_map_units_minus1 + 1
 * PicSizeInMbs = PicWidthInMbs * PicHeightInMbs
 * 
*/

namespace FormatTest
{
    /// <summary>
    /// 条带数据语法
    /// </summary>
    public class slice_data : base_func
    {
        public slice_data(string bytes)
        {
            base.bytes = bytes;
            if (DecodeH264.vpic_parameter_set_rbsp.entropy_coding_mode_flag != 0)
            {
                while (!byte_aligned())
                {
                    var cabac_alignment_one_bit = read_bits(1);
                }
            }

            var MbaffFrameFlag = (DecodeH264.vseq_parameter_set_rbsp.mb_adaptive_frame_field_flag & ~DecodeH264.vslice_header.field_pic_flag);
            var CurrMbAddr = DecodeH264.vslice_header.first_mb_in_slice * (1 + MbaffFrameFlag);
            var moreDataFlag = 1;
            var prevMbSkipped = 0;
            do
            {
                if (DecodeH264.vslice_header.slice_type != 2 && DecodeH264.vslice_header.slice_type != 7 && DecodeH264.vslice_header.slice_type != 4 && DecodeH264.vslice_header.slice_type != 9)
                {
                    if (~DecodeH264.vpic_parameter_set_rbsp.entropy_coding_mode_flag == 0)
                    {
                        var mb_skip_run = columbus_ue();
                        prevMbSkipped = (mb_skip_run > 0 ? 1 : 0);
                        for (var i = 0; i < mb_skip_run; i++)
                        {
                            CurrMbAddr = NextMbAddress(CurrMbAddr);
                        }
                    }
                }
            } while (moreDataFlag != 0);
            //DecodeH264.vseq_parameter_set_rbsp.mb_adaptive_frame_field_flag

            //MbaffFrameFlag = ( mb_adaptive_frame_field_flag && !field_pic_flag );
        }

        private int NextMbAddress(int currentMbAddress)
        {
            var i = currentMbAddress + 1;
            var PicWidthInMbs = DecodeH264.vseq_parameter_set_rbsp.pic_width_in_mbs_minus1 + 1;
            var PicHeightInMapUnits = DecodeH264.vseq_parameter_set_rbsp.pic_height_in_map_units_minus1 + 1;
            var PicSizeInMbs = (PicWidthInMbs) * (((2 - DecodeH264.vseq_parameter_set_rbsp.frame_mbs_only_flag) * (PicHeightInMapUnits)) / (1 + DecodeH264.vslice_header.field_pic_flag));
            var MapUnitsInSliceGroup0 = Math.Min(DecodeH264.vslice_header.slice_group_change_cycle,
DecodeH264.vpic_parameter_set_rbsp.SliceGroupChangeRate);
            //TODO:var sizeOfUpperLeftGroup=
            Dictionary<int, int> mapUnitToSliceGroupMap = GetMapUnitToSliceGroupMap(DecodeH264.vpic_parameter_set_rbsp.PicSizeInMapUnits, PicSizeInMbs, PicWidthInMbs, PicHeightInMapUnits, MapUnitsInSliceGroup0);
            while (i < PicSizeInMbs)
            {
                i++;
            }
            return i;
        }

        private Dictionary<int, int> GetMapUnitToSliceGroupMap(int PicSizeInMapUnits, int PicSizeInMbs, int PicWidthInMbs, int PicHeightInMapUnits, int MapUnitsInSliceGroup0)
        {
            Dictionary<int, int> mapUnitToSliceGroupMap = new Dictionary<int, int>();
            if (DecodeH264.vpic_parameter_set_rbsp.slice_group_map_type == 0)
            {
                //隔行扫描型条带组映射类型的规范
                var num = 0;
                do
                {
                    for (var iGroup = 0; iGroup < DecodeH264.vpic_parameter_set_rbsp.num_slice_groups_minus1 && num < PicSizeInMapUnits; num += DecodeH264.vpic_parameter_set_rbsp.run_length_minus1[iGroup++] + 1)
                    {
                        for (var j = 0; j <= DecodeH264.vpic_parameter_set_rbsp.run_length_minus1[iGroup] && num + j < PicSizeInMapUnits; j++)
                        {
                            mapUnitToSliceGroupMap[num + j] = iGroup;
                        }
                    }
                }
                while (num < PicSizeInMapUnits);
            }
            else if (DecodeH264.vpic_parameter_set_rbsp.slice_group_map_type == 1)
            {
                //分散型条带组映射的规范
                for (var num = 0; num < PicSizeInMapUnits; num++)
                {
                    mapUnitToSliceGroupMap[num] = ((num % PicSizeInMbs) + (((num / PicSizeInMbs) * (DecodeH264.vpic_parameter_set_rbsp.num_slice_groups_minus1 + 1)) / 2)) % (DecodeH264.vpic_parameter_set_rbsp.num_slice_groups_minus1 + 1);
                }
            }
            else if (DecodeH264.vpic_parameter_set_rbsp.slice_group_map_type == 2)
            {
                //具有参与条带组映射类型的前景规范
                for (var i = 0; i < PicSizeInMapUnits; i++)
                {
                    mapUnitToSliceGroupMap[i] = DecodeH264.vpic_parameter_set_rbsp.num_slice_groups_minus1;
                }
                for (var iGroup = DecodeH264.vpic_parameter_set_rbsp.num_slice_groups_minus1 - 1; iGroup >= 0; iGroup--)
                {
                    var yTopLeft = DecodeH264.vpic_parameter_set_rbsp.top_left[iGroup] / PicWidthInMbs;
                    var xTopLeft = DecodeH264.vpic_parameter_set_rbsp.top_left[iGroup] % PicWidthInMbs;
                    var yBottomRight = DecodeH264.vpic_parameter_set_rbsp.bottom_right[iGroup] / PicWidthInMbs;
                    var xBottomRight = DecodeH264.vpic_parameter_set_rbsp.bottom_right[iGroup] % PicWidthInMbs;
                    for (var y = yTopLeft; y <= yBottomRight; y++)
                    {
                        for (var x = xTopLeft; x <= xBottomRight; x++)
                        {
                            mapUnitToSliceGroupMap[y * PicWidthInMbs + x] = iGroup;
                        }
                    }
                }
            }
            else if (DecodeH264.vpic_parameter_set_rbsp.slice_group_map_type == 3)
            {
                for (var i = 0; i < PicSizeInMapUnits; i++)
                {
                    mapUnitToSliceGroupMap[i] = 1;
                }
                var x = (PicWidthInMbs - DecodeH264.vpic_parameter_set_rbsp.slice_group_change_direction_flag) / 2;
                var y = (PicHeightInMapUnits - DecodeH264.vpic_parameter_set_rbsp.slice_group_change_direction_flag) / 2;
                int leftBound = x, rightBound = x, topBound = y, bottomBound = y;
                int xDir = DecodeH264.vpic_parameter_set_rbsp.slice_group_change_direction_flag - 1;
                int yDir = DecodeH264.vpic_parameter_set_rbsp.slice_group_change_direction_flag;
                var mapUnitVacant = 0;
                for (var k = 0; k < MapUnitsInSliceGroup0; k += mapUnitVacant)
                {
                    mapUnitVacant = (mapUnitToSliceGroupMap[y * PicWidthInMbs + x] == 1) ? 0 : 1;
                    if (mapUnitVacant != 0)
                    {
                        mapUnitToSliceGroupMap[y * PicWidthInMbs + x] = 0;
                    }
                    if (xDir == -1 && x == leftBound)
                    {
                        leftBound = Math.Max(leftBound - 1, 0);
                        x = leftBound;
                        xDir = 0;
                        yDir = 1 - 2 * DecodeH264.vpic_parameter_set_rbsp.slice_group_change_direction_flag - 1;
                    }
                    else if (xDir == 1 && x == rightBound)
                    {
                        rightBound = Math.Min(rightBound + 1, PicWidthInMbs - 1);
                        x = rightBound;
                        xDir = 0;
                        yDir = 1 - 2 * DecodeH264.vpic_parameter_set_rbsp.slice_group_change_direction_flag;
                    }
                    else if (yDir == -1 && y == topBound)
                    {
                        topBound = Math.Max(topBound - 1, 0);
                        y = topBound;
                        xDir = 1 - 2 * DecodeH264.vpic_parameter_set_rbsp.slice_group_change_direction_flag;
                        yDir = 0;
                    }
                    else if (yDir == 1 && y == bottomBound)
                    {
                        bottomBound = Math.Min(bottomBound + 1, PicHeightInMapUnits - 1);
                        y = bottomBound;
                        xDir = 2 * DecodeH264.vpic_parameter_set_rbsp.slice_group_change_direction_flag;
                        yDir = 0;
                    }
                    else
                    {
                        x = x + xDir;
                        y = y + yDir;
                    }
                }
            }
            else if (DecodeH264.vpic_parameter_set_rbsp.slice_group_map_type == 4)
            {
                for (var i = 0; i < PicSizeInMapUnits; i++)
                {
                    //if (i < sizeOfUpperLeftGroup)
                    //{

                    //}
                }
            }

            return mapUnitToSliceGroupMap;
        }
    }
}
